#requires -version 2.0 
Function Get-NaISCSIInitiators {
	<#
	.Synopsis
  	 	Gives list of initiators logged in
	.Description
   		Gives list of initiators logged in
	.Parameter Server
   		NaServer to query
	.Example
		PS > Get-NaISCSIInitiators
	.Outputs
    	NetApp.SDK.NaiscsiInitiator[]
   	#> 
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param ( 
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		Try {
			$result = ([xml]$server.Invoke("iscsi-initiator-list-info")).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($? -and $result."iscsi-initiator-list-entries"){
			$result."iscsi-initiator-list-entries"."iscsi-initiator-list-entry-info" |% {
				return New-Object NetApp.SDK.NaiscsiInitiator -ArgumentList @(
					$_."initiator-aliasname",
					$_."initiator-nodename",
					[array]($_."initiator-group-list"."initiator-group-list-info"|%{$_."initiator-group-name"}),
					$_."isid",
					$_."target-session-id",
					$_."tpgroup-tag"
				)
			}
		}
	}
}
function Get-NaISCSIConnections {
	<#
	.Synopsis
  	 	list iscsi connections on filer
	.Description
   		list iscsi connections on filer
	.Parameter Server
   		NaServer to query
	.Example
		PS > Get-NaiscsiConnections
	.Outputs
    	NetApp.SDK.NaiscsiConnection[]
   	#> 
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param ( 
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		Try {
			$result = ([xml]$server.Invoke("iscsi-connection-list-info")).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?){
			$result."iscsi-connection-list-entries"."iscsi-connection-list-entry-info" |% {
				return New-Object NetApp.SDK.NaiscsiConnection -ArgumentList @(
					$_."interface-name",
					$_."local-ip-address",
					$_."local-ip-port",
					$_."remote-ip-address",
					$_."remote-ip-port",
					$_."connection-id",
					$_."connection-state",
					(Convertfrom-NaBool $_."has-session"),
					$_."session-id"
				)
			}
		}
	}
}
Function Get-NaISCSIPortal {
	<#
	.Synopsis
  	 	list iscsi portals
	.Description
   		list iscsi portals
	.Parameter Server
   		NaServer to query
	.Example
		PS > Get-NaISCSIPortal
	.Outputs
    	NetApp.SDK.NaiscsiPortal[]
    #> 
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param ( 
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		Try {
			$result = ([xml]$server.Invoke("iscsi-portal-list-info")).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($? -and $result."iscsi-portal-list-entries"." iscsi-portal-list-entry-info"){
			$result."iscsi-portal-list-entries"." iscsi-portal-list-entry-info" |% {
				return New-Object NetApp.SDK.NaiscsiPortal -ArgumentList @(
					$_."interface-name",
					$_."ip-address",
					$_."ip-port",
					$_."tpgroup-tag"
				)
			}
		}
	}
}
Function Get-NaISCSISessions {
	<#
	.Synopsis
  	 	Gives list of active sessions
	.Description
   		Gives list of active sessions
	.Parameter SessionID
		target session ID handle for specific session 
	.Parameter Server
   		NaServer to query
	.Example
		PS > Get-NaISCSISessions
	.Outputs
    	NetApp.SDK.NaiscsiSession[]
   	#> 
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param ( 
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,HelpMessage="target session ID handle for specific session ")]
		[int]
		$SessionID,

		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-session-list-info")
		if ($SessionID) {
			$request.AddNewChild("tsih",$SessionID)		
		}
		Try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?){
			$result."iscsi-session-list-entries"."iscsi-session-list-entry-info" |% {
				$session = New-Object NetApp.SDK.NaiscsiSession -ArgumentList @(
					$_."initiator-nodename",
					$_."initiator-aliasname",
					$_."session-type",
					$_."target-session-id",
					$_."tpgroup-tag",
					$_."isid",
					$_."max-connections",
					$_."cmd-window-size",
					$_."first-burst-length",
					$_."max-burst-length",
					$_."default-time-to-retain",
					$_."default-time-to-wait",
					$_."error-recovery-level",
					(Convertfrom-NaBool $_."data-pdu-in-order"),
					(Convertfrom-NaBool $_."data-sequence-in-order"),
					(Convertfrom-NaBool $_."immediate-data-enabled"),
					(Convertfrom-NaBool $_."initial-r2t-enabled"),
					$_."max-outstanding-r2t"
				)
	
				$_."iscsi-session-connection-list-entries"."iscsi-session-connection-list-entry-info" | % {
					$connection = New-Object NetApp.SDK.NaiscsiSessionConnection -ArgumentList @(
					$_."interface-name",
					$_."local-ip-address",
					$_."local-ip-port",
					$_."remote-ip-address",
					$_."remote-ip-port",
					$_."connection-id",
					(Convertfrom-NaBool $_."data-digest-enabled"),
					(Convertfrom-NaBool $_."header-digest-enabled"),
					$_."rcv-window-size",
					$_."initiator-max-rcv-data-segment-length",
					$_."target-max-rcv-data-segment-length",
					[array]($_."iscsi-sesssion-cmd-list-entries"."iscsi-sesssion-cmd-list-entry-info" | % {
						New-Object NetApp.SDK.NaiscsiCmdInfo -ArgumentList @(
						$_."cmd-state",
						$_."cmd-sub-id",
						$_."cmd-type"
						)
					})
					)
					$session.Connections.add([int]($_."connection-id"),$connection)
				}
				return $session
			}
		}
	}
}

Function Get-NaISCSIAlias {
	<#
	.Synopsis
  	 	Return the current iscsi target alias
	.Description
   		Return the current iscsi target alias
	.Parameter Server
   		NaServer to query
	.Example
		Get-NaISCSIAlias
	.Outputs
    	PSObject[]
    .Link
		Set-NaISCSIAlias
		Clear-NaISCSIAlias
   	#> 
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param ( 
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	try {
		$result = ([xml]$server.Invoke("iscsi-target-alias-get-alias")).results
	}
	catch [NetApp.Manage.NaApiFailedException]{
		Write-Warning $_.Exception.GetBaseException().message
		$result = $null
		continue;
	}
	if ($?){
		return $result | Select-Object `
		@{
			Name='Alias'
			Expression={$_."alias-name"}
		}, 
		@{
			Name='Assigned'
			Expression={(ConvertFrom-NaBool $_."is-alias-assigned")}
		}
	}
}
Function Set-NaISCSIAlias {
	<#
	.Synopsis
  	 	Set the current iscsi target alias
	.Description
   		Set the current iscsi target alias
	.Parameter Server
   		NaServer to query
	.Example
		Set-NaISCSIAlias -Name NetApp1
	.Outputs
    	PSObject[]
    .Link
		Get-NaISCSIAlias
		Clear-NaISCSIAlias
   	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="New iscsi target alias to set")]
		[Alias("alias")]
		[string]
		$Name,

		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-target-alias-set-alias")
		$request.AddNewChild("alias-name",$name)
		if ($pscmdlet.ShouldProcess($server.server,"Setting target alias to $name")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		} 
	}
}
Function Clear-NaISCSIAlias {
	<#
	.Synopsis
  	 	Clear the current iscsi target alias
	.Description
   		Clear the current iscsi target alias
	.Parameter Server
   		NaServer to query
	.Example
		Clear-NaISCSIAlias
    .Link
		Get-NaISCSIAlias
		Set-NaISCSIAlias
   	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-target-alias-clear-alias")
		if ($pscmdlet.ShouldProcess($server.server, "Clearing ISCSI target alias")) {
			try {
				$server.Invoke("iscsi-target-alias-clear-alias")|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		} 
	}
}
New-Alias -Name Remove-NaISCSIAlias -Value Clear-NaISCSIAlias

Function Get-NaISCSIInterface {
	<#
	.Synopsis
  	 	Gives status of interface for iSCSI
	.Description
   		Gives status of interface for iSCSI
   	.Parameter Name
   		Name of interface (e.g. e4) to report; if not supplied, all interfaces are listed 
	.Parameter Server
   		NaServer to query
	.Example
		PS > Get-NaISCSIInterface -Name e4
	.Outputs
		NetApp.SDK.NaiscsiInterface[]
    .Link
		Enable-NaISCSIInterface
		Disable-NaISCSIInterface
   	#> 
	[CmdletBinding(SupportsShouldProcess=$false,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")]
	param ( 
		[Parameter(position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of interface (e.g. e4) to report")]
		[Alias("Interface")]
		[string]
		$Name,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-interface-list-info")
		if ($Name) {
			$request.AddNewChild("interface-name",$name)
		}
		Try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?){
			$result."iscsi-interface-list-entries"."iscsi-interface-list-entry-info" |% {
				return New-Object NetApp.SDK.NaiscsiInterface -ArgumentList @(
					$_."interface-name",
					(ConvertFrom-NaBool $_."is-interface-enabled"),
					$_."tpgroup-name",
					$_."tpgroup-tag"
				)
			}
		}
	}
}
Function Enable-NaISCSIInterface {
	<#
	.Synopsis
  	 	Enables an interface for use by iSCSI
	.Description
   		Enables an interface for use by iSCSI
   	.Parameter Name
   		Name of interface to enable (example, "e4")
	.Parameter Server
   		NaServer to query
	.Example
		PS > Enable-NaISCSIInterface -Name e4
	.Outputs
		NetApp.SDK.NaiscsiInterface[]
    .Link
		Get-NaISCSIInterface
		Disable-NaISCSIInterface
   	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(Mandatory=$TRUE,position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of interface (e.g. e4) to Enable")]
		[Alias("Interface")]
		[string]
		$Name,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-interface-enable")
		$request.AddNewChild("interface-name",$Name)
		if ($pscmdlet.ShouldProcess($Server.server, "Enabling ISCSI on $Name")) {
			Try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				return Get-NaISCSIInterface -Name $Name -Server $Server
			}
		} 
	}
}
Function Disable-NaISCSIInterface {
	<#
	.Synopsis
  	 	Disable an interface for use by iSCSI
	.Description
   		Disable an interface for use by iSCSI
   	.Parameter Name
   		Name of interface to disable (example, "e4")
	.Parameter Server
   		NaServer to query
	.Example
		PS > Disable-NaISCSIInterface -Name e4
	.Outputs
		NetApp.SDK.NaiscsiInterface[]
    .Link
		Get-NaISCSIInterface
		Enable-NaISCSIInterface
   	#> 
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(Mandatory=$TRUE,position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of interface (e.g. e4) to Disable")]
		[Alias("Interface")]
		[string]
		$Name,

		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-interface-disable")
		$request.AddNewChild("interface-name",$name)
		if ($pscmdlet.ShouldProcess($Server.server, "disabling ISCSI on $Name")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				return Get-NaISCSIInterface -Name $Name -Server $server
			}
		} 
	}
}

Function Test-NaISCSIService {
	<#
	.Synopsis
  	 	Get status of the iSCSI service, whether or not it is running.
	.Description
   		Cmdlet will return TRUE if the iSCSI service is running, and 
   		False if it is stopped.
   	.Parameter Server
   		NaServer to query
	.Example
		PS > Test-NaISCSIService
	.Outputs
		bool
    .Link
		Start-NaISCSIService
		Stop-NaISCSIService
   	#> 
	[CmdletBinding(SupportsShouldProcess=$false,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")]
	param ( 
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		Try {
			return convertfrom-nabool ([xml]$server.Invoke("iscsi-service-status")).results."is-available"
		}
		catch [NetApp.Manage.NaApiFailedException] {
			Write-Warning $_.Exception.GetBaseException().message
			return $null
		}
	}
}
Function Start-NaISCSIService {
	<#
	.Synopsis
  	 	Start iSCSI service.
	.Description
   		Start iSCSI service. Service will be avaliable once the call returns with success.
   	.Parameter Server
   		NaServer to query
	.Example
		PS > Start-NaISCSIService
    .Link
		Test-NaISCSIService
		Stop-NaISCSIService
   	#> 
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		if ($pscmdlet.ShouldProcess($server.server,"Starting the ISCSI service")) {
			try {
				$server.Invoke("iscsi-service-start")|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		} 
	}
}
Function Stop-NaISCSIService {
	<#
	.Synopsis
  	 	Stop iSCSI service.
	.Description
   		Stop iSCSI service. Service will be stopped once the call returns with success.
   	.Parameter Server
   		NaServer to query
	.Example
		PS > Stop-NaISCSIService
    .Link
		Test-NaISCSIService
		Start-NaISCSIService
   	#> 
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		if ($pscmdlet.ShouldProcess($server.Server,"Stopping the ISCSI service")) {
			try {
				$server.Invoke("iscsi-service-stop")|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		} 
	}
}

Function Get-NaISCSINodeName {
	<#
	.Synopsis
  	 	Return the current iscsi node name.
	.Description
   		Return the current iscsi node name.
   	.Parameter Server
   		NaServer to query
	.Example
		PS > Get-NaISCSINodeName
	.Outputs
		string
    .Link
		Get-NaISCSINodeName
   	#> 
	[CmdletBinding(SupportsShouldProcess=$false,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")]
	param ( 
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		Try {
			$result = ([xml]$server.Invoke("iscsi-node-get-name")).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?){
			return $result."node-name"
		}
	}
}
Function Set-NaISCSINodeName {
	<#
	.Synopsis
  	 	Set the current iscsi node name.
	.Description
   		Set the current iscsi node name.
   	.Parameter Name
   		New iscsi node name; must be <= 128 chars, and conform to iSCSI rules
   	.Parameter Server
   		NaServer to query
	.Example
		PS > Set-NaISCSINodeName -Name iqn.1992-08.com.netapp:TOASTER01
	.Outputs
		string
    .Link
		Get-NaISCSINodeName
   	#> 
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="New iscsi node name")]
		[Alias("NodeName")]
		[string]
		$Name,

		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-node-set-name")
		$request.AddNewChild("node-name",$Name)
		if ($pscmdlet.ShouldProcess($server.server, "Setting the iSCSI node name to $Name")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				return Get-NaISCSINodeName -Server $Server
			}
		} 
	}
}

Function Get-NaISNS {
	<#
	.Synopsis
  	 	Gets iSNS service configuration.
	.Description
   		Gets iSNS service configuration.
   	.Parameter Server
   		NaServer to query
	.Example
		PS > Get-NaISNS
	.Outputs
		NetApp.SDK.Naisns[]
    .Link
		Get-NaISNS
		Set-NaISNS
		Start-NaISNS
		Stop-NaISNS
		Update-NaISNS
   	#> 
	[CmdletBinding(SupportsShouldProcess=$false,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")]
	param ( 
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		Try {
			$result = ([xml]$server.Invoke("iscsi-isns-get-info")).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			return $null
		}
		if ($? -and $result."is-isns-enabled"){
			return New-Object NetApp.SDK.Naisns -ArgumentList @(
				$result."isns-ip-addr",
				$result."isns-entity-id",
				(ConvertFrom-NaBool $result."is-isns-enabled")
			)
		}
	}
}
Function Set-NaISNS {
	<#
	.Synopsis
  	 	Configures the iSNS service.
	.Description
   		Configures the iSNS service.
   	.Parameter IP
   		The ip address, in dotted-decimal format, of the iSNS server with which
   		to register. (for example, "192.168.11.12").
   	.Parameter Server
   		NaServer to query
	.Example
		PS > Set-NaISNS -Server 192.168.1.1
	.Outputs
		NetApp.SDK.Naisns[]
    .Link
		Get-NaISNS
		Start-NaISNS
		Stop-NaISNS
		Update-NaISNS
   	#> 
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The ip address of the iSNS server with which to register.")]
		[ValidatePattern("(2[0-4]\d|25[0-5]|[01]?\d\d?)\.(2[0-4]\d|25[0-5]|[01]?\d\d?)\.(2[0-4]\d|25[0-5]|[01]?\d\d?)\.(2[0-4]\d|25[0-5]|[01]?\d\d?)")]
		[Alias("isnsIP")]
		[string]
		$IP,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-isns-config")
		$request.AddNewChild("isns-ip-addr",$IP)
		if (($pscmdlet.ShouldProcess($server.server, "Configuring the iSNS Service for $IP"))) {
			Try {
				$result = ([xml]$server.InvokeElem($request)).results
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				$result = $null
				continue;
			}
			if ($?){
				return Get-NaISNS -Server $server
			}
		} 
	}
}
Function Start-NaISNS {
	<#
	.Synopsis
  	 	Start iSNS service. 
	.Description
   		Start iSNS service. Service will be avaliable once the call returns with success.
   	.Parameter Server
   		NaServer to query
	.Example
		PS > Start-NaISNS
    .Link
		Get-NaISNS
		Set-NaISNS
		Stop-NaISNS
		Update-NaISNS
   	#> 
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		if ($pscmdlet.ShouldProcess($server.server, "Starting the iSNS service")) {
			try {
				$server.Invoke("iscsi-isns-start")|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		} 
	}
}
Function Stop-NaISNS {
	<#
	.Synopsis
  	 	Stop iSNS service. 
	.Description
   		Stop iSNS service. Service will not be avaliable once the call returns with success.
   	.Parameter Server
   		NaServer to query
	.Example
		PS > Stop-NaISNS
    .Link
		Get-NaISNS
		Set-NaISNS
		Start-NaISNS
		Update-NaISNS
   	#> 
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		if ($pscmdlet.ShouldProcess($server.server, "Stopping the iSNS service")) {
			try {
				$server.InvokeElem("iscsi-isns-stop")|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		} 
	}
}
Function Update-NaISNS  {
	<#
	.Synopsis
  	 	Forces iSNS service to update server.
	.Description
   		Forces iSNS service to update server.
   	.Parameter Server
   		NaServer to query
	.Example
		PS > Update-NaISNS
    .Link
		Get-NaISNS
		Set-NaISNS
		Start-NaISNS
		Stop-NaISNS
   	#> 
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		if ($pscmdlet.ShouldProcess($server.server, "Forcing iSNS service to update server.")) {
			try {
				$server.Invoke("iscsi-isns-stop")|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		} 
	}
}

Function Get-NaISCSIAuthentication {
	<#
	.Synopsis
  	 	Get authentication information for the specified initiator
	.Description
   		Get authentication information for the specified initiator If no initiator
   		is specified, get authentication infomation for all the known initiators. 
   		Password, if present is left out for security purposes.
   	.Parameter Name
   		Name of initiator. i.e. iqn.1987-06.com.initvendor1:appsrv.sn.2346. 
   		If initiator is not supplied, all initiators are returned. 
   	.Parameter Server
   		NaServer to query
	.Example
		# Get the authentication information for all initiators
		PS > Get-NaISCSIAuthentication
	.Example
		# Get the authentication information for 
		PS > Get-NaISCSIAuthentication -Name iqn.1987-06.com.microsoft:server1
	.Outputs
		NetApp.SDK.NaiscsiSecurity[]
    .Link
		Add-NaISCSIAuthentication
		Set-NaISCSIAuthentication
		Remove-NaISCSIAuthentication
		Get-NaISCSIDefaultAuthentication
		Set-NaISCSIDefaultAuthentication
   	#> 
	[CmdletBinding(SupportsShouldProcess=$false,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")]
	param ( 
		[Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of initiator. i.e. iqn.1987-06.com.initvendor1:appsrv.sn.2346.")]
		[Alias("Initiator")]
		[string]
		$Name,
 
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-initiator-auth-list-info")
		if ($Name) {
			$request.AddNewChild("initiator",$name)
		}
		Try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($? -and $result."iscsi-security-entries"){
			$result."iscsi-security-entries"."iscsi-security-entry-info" |% {
				return New-Object NetApp.SDK.NaiscsiSecurity -ArgumentList @(
					$_."initiator",
					$_."auth-type",
					$_."outbound-user-name",
					$_."user-name"
				)
			}
		}
	}
}
Function Add-NaISCSIAuthentication {
	<#
	.Synopsis
  	 	Add initiator to the authentication list.
	.Description
   		Add initiator to the authentication list.
   	.Parameter Name
   		Name of initiator. i.e. iqn.1987-06.com.initvendor1:appsrv.sn.2346. 
   	.Parameter Type
   		Authentication type, possible values : CHAP, none, deny. 
   	.Parameter OutboundCredentital
   		Outbound authentication is optional. If Outbound authentication is not 
   		specified, then the initiator can only do inbound traffic.
   	.Parameter InboundCredentital
   		Inbound CHAP Credential, required for auth-type equals to CHAP. 
   	.Parameter Server
   		NaServer to query
	.Example
		# Add CHAP authentication to the iqn.1987-06.com.microsoft:server1 initiator
		PS > $initiator = "iqn.1987-06.com.microsoft:server1"
		PS > $InboundCreds = Get-Credential
		PS > Get-NaISCSIAuthentication -Name $initiator -Type CHAP -InboundCredentital $InboundCreds 
	.Example
		# Deny authentication to the iqn.1987-06.com.microsoft:server1 initiator
		PS > $initiator = "iqn.1987-06.com.microsoft:server1"
		PS > Get-NaISCSIAuthentication -Name $initiator -Type deny
	.Outputs
		NetApp.SDK.NaiscsiSecurity[]
    .Link
		Get-NaISCSIAuthentication
		Set-NaISCSIAuthentication
		Remove-NaISCSIAuthentication
		Get-NaISCSIDefaultAuthentication
		Set-NaISCSIDefaultAuthentication
   	#> 
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of initiator.")]
		[Alias("initiator")]
		[string]
		$Name,
	
		[Parameter(Position=1,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Authentication type, possible values : CHAP, none, deny. ")]
		[ValidateSet("CHAP","none","deny")]
		[string]
		$Type,
	
		[Parameter(HelpMessage="Outbound CHAP Credential.")]
		[System.Management.Automation.PSCredential]
		$OutboundCredentital,
		
		[Parameter(HelpMessage="Inbound CHAP Credential, required for auth-type equals to CHAP.")]
		[System.Management.Automation.PSCredential]
		$InboundCredentital,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	begin {
		if (($type -match "CHAP") -and -not $InboundCredentital) {
			Throw "-InboundUserName and -InboundPassword are required when using -type CHAP!"
		}
	}
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-initiator-add-auth")
		$request.AddNewChild("initiator",$Name)
		$request.AddNewChild("auth-type",$Type)
		if ($InboundCredential) {
			$cred = $InboundCredential.GetNetworkCredential()
			$request.AddNewChild("user-name",$cred.UserName)
			$request.AddNewChild("password",$cred.Password)
			$Cred=$null
		}
		if ($OutboundCredential) {
			$cred = $InboundCredential.GetNetworkCredential()
			$request.AddNewChild("outbound-user-name",$cred.Username)
			$request.AddNewChild("outbound-password",$cred.Password)
			$Cred = $Null
		}
		if ($pscmdlet.ShouldProcess($Server.server, "Configuring $type authentication on $Name")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				$result = $null
				continue;
			}
			if ($?){
				return Get-NaISCSIAuthentication -Name $Name -Server $Server
			}
		} 
	}
}
Function Set-NaISCSIAuthentication {
	<#
	.Synopsis
  	 	Modify CHAP parameters to an existing per-initiator authentication info.
	.Description
   		Modify CHAP parameters to an existing per-initiator authentication info
   		whose auth-type equals CHAP.
   	.Parameter Name
   		Name of initiator. i.e. iqn.1987-06.com.initvendor1:appsrv.sn.2346.
   		The per-initiator authentication info must have an auth-type equal to CHAP.  
   	.Parameter RemoveOutbound
   		Flag which indicates that mutual CHAP authentication is to be converted to 
   		one-way CHAP authentication. 
   	.Parameter OutboundCredential
   		If Outbound CHAP parameters are specified they will replace existing 
   		Outbound CHAP parameters. If no Outbound CHAP parameters were previously
   		specified, then the specified Outbound CHAP parameters will enable mutual 
   		CHAP authentication. If no Outbound CHAP parameters are specified and no 
   		Outbound CHAP parameters exist, then one-way Inbound CHAP authentication 
   		will be continue to be used. 
   	.Parameter InboundCredential
   		If Inbound CHAP parameters are specified they will replace the existing 
   		Inbound CHAP parameters. If they are not specified, the existing Inbound 
   		CHAP parameters will continue to be used. 
   	.Parameter Server
   		NaServer to query
	.Example
		# Remove outbound credentials for all initiators
		PS > Get-NaISCSIInitiators | Set-NaISCSIAuthentication -RemoveOutbound
	.Example
		# Change the outbound credentials for iqn.1987-06.com.initvendor1:appsrv.sn.2346
		PS > $Cred = Get-Credential
		PS > $Initiator = iqn.1987-06.com.initvendor1:appsrv.sn.2346
		PS > Set-NaISCSIAuthentication -Name $Initiator -OutboundCredential 
	.Outputs
		NetApp.SDK.NaiscsiSecurity[]
    .Link
		Get-NaISCSIAuthentication
		Add-NaISCSIAuthentication
		Remove-NaISCSIAuthentication
		Get-NaISCSIDefaultAuthentication
		Set-NaISCSIDefaultAuthentication
   	#> 
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of initiator.")]
		[Alias("initiator")]
		[string]
		$Name,
	
		[Parameter()]
		[switch]
		$RemoveOutbound,
	
		[Parameter(HelpMessage="Outbound CHAP Credentials.")]
		[System.Management.Automation.PSCredential]
		$OutboundCredential,
	
		[Parameter(HelpMessage="Inbound CHAP Credentials.")]
		[System.Management.Automation.PSCredential]
		$InboundCredential,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	begin {
		if ($OutboundCredential -and $RemoveOutbound) {
			Throw "-OutboundCredential and -RemoveOutbound cannot be supplied together!"
		}
	}
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-initiator-modify-chap-params")
		$request.AddNewChild("initiator",$Name)
		if ($InboundCredential) {
			$cred = $InboundCredential.GetNetworkCredential()
			$request.AddNewChild("user-name",$cred.UserName)
			$request.AddNewChild("password",$cred.Password)
			$Cred=$null
		}
		if ($removeOutbound) {
			$request.AddNewChild("remove-outbound",$TRUE)
		} elseif ($OutboundCredential) {
			$cred = $InboundCredential.GetNetworkCredential()
			$request.AddNewChild("outbound-user-name",$cred.Username)
			$request.AddNewChild("outbound-password",$cred.Password)
			$Cred = $Null
		}
		if ($pscmdlet.ShouldProcess($Server.server, "Updating Security on $Name")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				return Get-NaISCSIAuthentication -Name $Name -server $server
			}
		} 
	}
}
Function Remove-NaISCSIAuthentication {
	<#
	.Synopsis
  	 	Delete initiator from the authentication list
	.Description
   		Delete initiator from the authentication list
   	.Parameter Name
   		Name of initiator. i.e. iqn.1987-06.com.initvendor1:appsrv.sn.2346. 
   	.Parameter Server
   		NaServer to query
	.Example
		# Remove authentication from all initiators
		PS > Get-NaISCSIInitiators | Remove-NaISCSIAuthentication
	.Example
		# Remove authentication from the iqn.1987-06.com.microsoft:server1 initiator
		PS > Remove-NaISCSIAuthentication -Name "iqn.1987-06.com.microsoft:server1"
	.Link
		Get-NaISCSIAuthentication
		Set-NaISCSIAuthentication
		Add-NaISCSIAuthentication
		Get-NaISCSIDefaultAuthentication
		Set-NaISCSIDefaultAuthentication
   	#> 
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of initiator.")]
		[Alias("initiator")]
		[string]
		$Name,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-initiator-delete-auth")
		$request.AddNewChild("initiator",$Name)
		if ($pscmdlet.ShouldProcess($server.server, "Removing initiator authentication from $name")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		} 
	}
}

Function Get-NaISCSIDefaultAuthentication {
	<#
	.Synopsis
  	 	Get the default auth info for iscsi.
	.Description
   		Get the default auth info for iscsi. If the auth type is CHAP, only the 
   		username is retuned, and not the password, for security purposes.
   	.Parameter Server
   		NaServer to query
	.Example
		# Get the Default authentication information for the filer
		PS > Get-NaISCSIDefaultAuthentication
	.Outputs
		NetApp.SDK.NaiscsiSecurity
    .Link
		Add-NaISCSIAuthentication
		Set-NaISCSIAuthentication
		Remove-NaISCSIAuthentication
		Get-NaISCSIAuthentication
		Set-NaISCSIDefaultAuthentication
   	#> 
	[CmdletBinding(SupportsShouldProcess=$false,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")]
	param ( 
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-initiator-get-default-auth")
		Try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?){
			return New-Object NetApp.SDK.NaiscsiSecurity -ArgumentList @(
				"Default",
				$result."auth-type",
				$result."outbound-user-name",
				$result."user-name"
			)
		}
	}
}
Function Set-NaISCSIDefaultAuthentication {
	<#
	.Synopsis
  	 	Configure the default authentication method.
	.Description
   		Configure the default authentication method. If an initiator is not configured 
   		with a specific authentication method using iscsi-security-add the default 
   		authentication method will be applied to it.
   	.Parameter Type
   		Possible values: CHAP, none, deny. 
   	.Parameter OutboundCredential
   		If Outbound CHAP parameters are specified they will replace existing 
   		Outbound CHAP parameters. If no Outbound CHAP parameters were previously
   		specified, then the specified Outbound CHAP parameters will enable mutual 
   		CHAP authentication. If no Outbound CHAP parameters are specified and no 
   		Outbound CHAP parameters exist, then one-way Inbound CHAP authentication 
   		will be continue to be used. 
   	.Parameter InboundCredential
   		Inbound CHAP Credentials, required for auth-type equals to CHAP. 
   	.Parameter Server
   		NaServer to query
	.Example
		# Set the default iSCSI autentication to none 
		PS > Set-NaISCSIDefaultAuthentication -type none
	.Example
		# Set the default iSCSI autentication to CHAP 
		PS > $Cred = Get-Credential
		PS > Set-NaISCSIDefaultAuthentication -type CHAP -OutboundCredential 
	.Outputs
		NetApp.SDK.NaiscsiSecurity[]
    .Link
		Get-NaISCSIAuthentication
		Add-NaISCSIAuthentication
		Remove-NaISCSIAuthentication
		Set-NaISCSIAuthentication
		Get-NaISCSIDefaultAuthentication
   	#> 
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Authentication type, possible values : CHAP, none, deny. ")]
		[ValidateSet("CHAP","none","deny")]
		[string]
		$Type,
	
		[Parameter(HelpMessage="Outbound CHAP Credential.")]
		[System.Management.Automation.PSCredential]
		$OutboundCredentital,
		
		[Parameter(HelpMessage="Inbound CHAP Credential, required for auth-type equals to CHAP.")]
		[System.Management.Automation.PSCredential]
		$InboundCredentital,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	begin {
		if (($type -match "CHAP") -and -not $InboundCredentital) {
			Throw "-InboundUserName and -InboundPassword are required when using -type CHAP!"
		}
	}
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-initiator-set-default-auth")
		$request.AddNewChild("auth-type",$Type)
		if ($InboundCredential) {
			$cred = $InboundCredential.GetNetworkCredential()
			$request.AddNewChild("user-name",$cred.UserName)
			$request.AddNewChild("password",$cred.Password)
			$Cred=$null
		}
		if ($OutboundCredential) {
			$cred = $InboundCredential.GetNetworkCredential()
			$request.AddNewChild("outbound-user-name",$cred.Username)
			$request.AddNewChild("outbound-password",$cred.Password)
			$Cred = $Null
		}
		if ($pscmdlet.ShouldProcess($Server.server, "Setting default authentication to $type")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				return Get-NaISCSIDefaultAuthentication -Server $Server
			}
		} 
	}
}

Function Get-NaTPGroup {
	<#
	.Synopsis
  	 	List information about target portal groups
	.Description
   		List information about target portal groups
   	.Parameter Name
   		Portal group being queried; if not supplied, information on all portal
   		groups is returned 
   	.Parameter Server
   		NaServer to query
	.Example
	
	.Outputs
		NetApp.SDK.NaiscsiTPGroup[]
    .Link
		Get-NaTPGroup
		Set-NaTPGroup
		New-NaTPGroup
		Remove-NaTPGroup
		Add-NaTPGroupInterface
		Remove-NaTPGroupInterface
   	#> 
	[CmdletBinding(SupportsShouldProcess=$false,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")]
	param ( 
		[Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Portal group being queried")]
		[Alias("Name")]
		[int]
		$TPGroupTag,
		
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-tpgroup-list-info")
		if ($name) {
			$request.AddNewChild("tpgroup-tag",$name)
		}
		Try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?){
			$result."iscsi-tpgroup-list-entries"."iscsi-tpgroup-list-entry-info" |% {
				return New-Object NetApp.SDK.NaiscsiTPGroup -ArgumentList @(
					$_."tpgroup-name", 
					$_."tpgroup-tag",
					[array]($_."interface-list-entries"."interface-list-entry-info" | %{$_."interface-name"}),
					$_."tpgroup-alua-state",
					(ConvertFrom-NaBool $_."tpgroup-alua-preferred")
				)
			}
		}
	}
}
Function New-NaTPGroup {
	<#
	.Synopsis
  	 	List information about target portal groups
	.Description
   		List information about target portal groups
   	.Parameter Name
   		User-defined name of new target portal group; must be <= 32 bytes, and cannot
   		end with "default" as this might conflict with names of default system portal
   		groups 
	.Parameter TPGroupTag
		Optional target portal group tag supplied by user; if not supplied, system 
		assigns tag. 
	.Parameter Preferred
		target portal group will be marked as preferred for ALUA enabled Initiator 
		Groups.
	.Parameter ALUAState
   		Set the state of Asymmetric Logical Unit Access 
   		possible values: 'optimized', 'non-optimized'
   	.Parameter Server
   		NaServer to query
	.Example
	
	.Outputs
		NetApp.SDK.NaiscsiTPGroup[]
    .Link
		Get-NaTPGroup
		Set-NaTPGroup
		New-NaTPGroup
		Remove-NaTPGroup
		Add-NaTPGroupInterface
		Remove-NaTPGroupInterface
   	#> 
	[CmdletBinding(SupportsShouldProcess=$false,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")]
	param ( 
		[Parameter(Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="User-defined name of new target portal group")]
		[Alias("TPGroup")]
		[string]
		$Name,
		
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Optional target portal group tag supplied by user")]
		[int]
		$TPGroupTag,
		
		[Parameter()]
		[switch]
		$Preferred,
		
		[Parameter(HelpMessage="Set the state of Asymmetric Logical Unit Access.")]
		[ValidateSet("optimized", "non-optimized" )]
		[string]
		$ALUAState,
		
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer]
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-tpgroup-create")
		$request.AddNewChild("tpgroup-name",$Name)
		if ($TPGroupTag) {
			$request.AddNewChild("tpgroup-name",$TPGroupTag)
		}
		if ($ALUAState) {
			if ($pscmdlet.ShouldProcess($Server.server, "Creating TPGroup $name")) {
				try {
					$tag = $server.InvokeElem($request).GetChildContent("tpgroup-tag")
				}
				catch [NetApp.Manage.NaApiFailedException]{
					Write-Warning $_.Exception.GetBaseException().message
					$result = $null
					continue;
				}
				if ($?){
					if ($Preferred) {
						Set-NaTPGroup -Name $tag -ALUAState $ALUAState -Preferred -Server $server
					} else {
						Set-NaTPGroup -Name $tag -ALUAState $ALUAState -Server $server
					}
					return Get-NaTPGroup -TPGroupTag $tag
				}
			}
		}
		else {
			if ($pscmdlet.ShouldProcess($server.server, "Creating TPGroup $Name")) {
				try {
					$tag = $server.InvokeElem($request).GetChildContent("tpgroup-tag")
				}
				catch [NetApp.Manage.NaApiFailedException]{
					Write-Warning $_.Exception.GetBaseException().message
					$result = $null
					continue;
				}
				if ($?){
					return Get-NaTPGroup -TPGroupTag $tag
				}
			}
		}
	}
}
Function Set-NaTPGroup {
	<#
	.Synopsis
  	 	Change the ALUA parameters on a tpgroup.
	.Description
   		Change the ALUA parameters on a tpgroup Asymmetric Logical Unit Access (ALUA) 
   		management Data ONTAP supports SCSI ALUA functionality for managing multi-pathed
   		SCSI devices. ALUA provides a standardized mechanism for path discovery and 
   		prioritization. Devices are identified by target port IDs, which are then 
   		grouped into target port groups. Each group has a state which, when configured,
   		enables the host multipathing software to select the appropriate path priorities
   		when accessing a LUN. For iSCSI, ALUA settings are controlled at the target 
   		portal group level using the Set-NaTPGroup cmdlet. A target portal group can be
   		configured to be either "optimized" or "non-optimized"; a host typically uses 
   		all the optimized paths before using any non-optimized paths it may find. All
   		target portal groups are optimized by default. There is also an optional 
   		"preferred" setting that may be used on a target portal group. Check your host's 
   		multi-pathing software documentation to see if it supports ALUA and the preferred
   		setting. ALUA is enabled on Initiator Groups using the Set-NaIGroup cmdlet. 
   		All LUNs mapped to an ALUA enabled Initiator Group will support the ALUA 
   		functionality. 
  	.Parameter Name
		Portal Group
	.Parameter Preferred
		target portal group will be marked as preferred for ALUA enabled Initiator 
		Groups.
	.Parameter ALUAState
   		Set the state of Asymmetric Logical Unit Access 
   		possible values: 'optimized', 'non-optimized'
   	.Parameter Server
   		NaServer to query
	.Example
	
	.Outputs
		NetApp.SDK.NaiscsiTPGroup[]
    .Link
		Get-NaTPGroup
		New-NaTPGroup
		Remove-NaTPGroup
		Add-NaTPGroupInterface
		Remove-NaTPGroupInterface
   	#> 
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Optional target portal group tag supplied by user; if not supplied, system assigns tag.")]
		[Alias("Name")]
		[int]
		$TPGroupTag,
		
		[Parameter()]
		[switch]
		$Preferred,
		
		[Parameter(Mandatory=$TRUE,HelpMessage="Set the state of Asymmetric Logical Unit Access possible values: 'optimized', 'non-optimized'")]
		[ValidateSet("optimized", "non-optimized" )]
		[string]
		$ALUAState,
		
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-tpgroup-alua-set")
		$request.AddNewChild("tpgroup-tag",$TPGroupTag)
		if ($ALUAState) {
			$request.AddNewChild("tpgroup-alua-state",$ALUAState)
		}
		if ($Preferred) {
			$request.AddNewChild("tpgroup-alua-preferred",$TRUE)
		} else {
			$request.AddNewChild("tpgroup-alua-preferred",$FALSE)
		}
		if ($pscmdlet.ShouldProcess($Server.server,"Setting the ALUA Settings for TPGroup $name")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				return Get-NaTPGroup -TPGroupTag $TPGroupTag -Server $Server
			}
		}
	}
}
Function Remove-NaTPGroup {
	<#
	.Synopsis
  	 	Destroy a target portal group
	.Description
   		Destroy a target portal group
   	.Parameter Name
   		tag of portal group to destroy 
   	.Parameter Server
   		NaServer to query
	.Example
	
    .Link
		Get-NaTPGroup
		Set-NaTPGroup
		New-NaTPGroup
		Add-NaTPGroupInterface
		Remove-NaTPGroupInterface
   	#> 
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="tag of portal group to destroy")]
		[Alias("Name")]
		[int]
		$TPGroupTag,
		
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-tpgroup-destroy")
		$request.AddNewChild("tpgroup-tag",$TPGroupTag)
		if ($pscmdlet.ShouldProcess($Server.server,"Destroying TPGroup $Name")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		} 
	}
}

Function Add-NaTPGroupInterface {
	<#
	.Synopsis
  	 	Add an interface to a target portal group
	.Description
   		Add an interface to a target portal group
   	.Parameter Name
   		name of network interface being added 
	.Parameter TPGroupTag
		portal group tag 
   	.Parameter Server
   		NaServer to query
	.Example
	
	.Outputs
		NetApp.SDK.NaiscsiTPGroup[]
    .Link
		Get-NaTPGroup
		Set-NaTPGroup
		New-NaTPGroup
		Remove-NaTPGroup
		Remove-NaTPGroupInterface
   	#> 
	param ( 
		[Parameter(position=0,Mandatory=$TRUE,HelpMessage="name of network interface being added ")]
		[Alias("Interface")]
		[string]
		$Name,
		
		[Parameter(position=1,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="portal group tag")]
		[int]
		$TPGroupTag,
		
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-tpgroup-interface-add")
		$request.AddNewChild("tpgroup-tag",$TPGroupTag)
		$request.AddNewChild("interface-name",$Name)
		if ($pscmdlet.ShouldProcess($Server.server,"Add $name to TPGroup $TPGroupTag")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				return Get-NaTPGroup -TPGroupTag $TPGroupTag -Server $Server
			}
		}
	}
}
Function Remove-NaTPGroupInterface {
	<#
	.Synopsis
  	 	Remove an interface from the target portal group
	.Description
   		remove an interface from the target portal group
   	.Parameter Name
   		name of network interface being removed 
	.Parameter TPGroupTag
		portal group tag 
   	.Parameter Server
   		NaServer to query
	.Example
	
	.Outputs
		NetApp.SDK.NaiscsiTPGroup[]
    .Link
		Get-NaTPGroup
		Set-NaTPGroup
		New-NaTPGroup
		Remove-NaTPGroup
		Add-NaTPGroupInterface
   	#> 
	param ( 
		[Parameter(position=0,Mandatory=$TRUE,HelpMessage="name of network interface being Removed ")]
		[Alias("Interface")]
		[string]
		$Name,
		
		[Parameter(position=1,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="portal group tag")]
		[int]
		$TPGroupTag,
		
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("iscsi-tpgroup-interface-delete")
		$request.AddNewChild("tpgroup-tag",$TPGroupTag)
		$request.AddNewChild("interface-name",$Name)
		if ($pscmdlet.ShouldProcess($Server.Server,"removing $Name from TPGroup $TPGroupTag")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		}
	}
}
